<template>
  <div class="ui-lyric-warp">
    <div class="ui-lyric-container">
      <ul class="ui-lyric-list">
        <li
          v-for="(item,i) in lyricArr"
          :key="i"
          class="ui-lyric-item"
          :class="{active:curLyric.time===item.time}"
          :data-time="item.time"
        >
          {{ item.text }}
        </li>
        <li v-if="lyricArr.length===0&&!loading" class="ui-lyric-item">
          暂无歌词
        </li>
      </ul>
    </div>
    <svg
      v-if="loading"
      width="120"
      height="30"
      class="lyric-loading"
      viewBox="0 0 120 30"
      xmlns="http://www.w3.org/2000/svg"
      fill="#999"
    >
      <circle cx="15" cy="15" r="15">
        <animate
          attributeName="r"
          from="15"
          to="15"
          begin="0s"
          dur="0.8s"
          values="15;9;15"
          calcMode="linear"
          repeatCount="indefinite"
        />
        <animate
          attributeName="fill-opacity"
          from="1"
          to="1"
          begin="0s"
          dur="0.8s"
          values="1;.5;1"
          calcMode="linear"
          repeatCount="indefinite"
        />
      </circle>
      <circle cx="60" cy="15" r="9" fill-opacity="0.3">
        <animate
          attributeName="r"
          from="9"
          to="9"
          begin="0s"
          dur="0.8s"
          values="9;15;9"
          calcMode="linear"
          repeatCount="indefinite"
        />
        <animate
          attributeName="fill-opacity"
          from="0.5"
          to="0.5"
          begin="0s"
          dur="0.8s"
          values=".5;1;.5"
          calcMode="linear"
          repeatCount="indefinite"
        />
      </circle>
      <circle cx="105" cy="15" r="15">
        <animate
          attributeName="r"
          from="15"
          to="15"
          begin="0s"
          dur="0.8s"
          values="15;9;15"
          calcMode="linear"
          repeatCount="indefinite"
        />
        <animate
          attributeName="fill-opacity"
          from="1"
          to="1"
          begin="0s"
          dur="0.8s"
          values="1;.5;1"
          calcMode="linear"
          repeatCount="indefinite"
        />
      </circle>
    </svg>
    <slot />
  </div>
</template>
<script>
export default {
  name: 'UiLyric',
  props: {
    sourceLyric: {
      type: String,
      default: ''
    },
    offset: {
      type: Number,
      default: 0
    },
    curTime: {
      type: Number,
      default: 0
    },
    loading: {
      type: Boolean,
      default: false
    }
  },
  data() {
    return {
      lyricArr: [],
      curLyric: {}
    }
  },
  watch: {
    curTime(val, oldVal) {
      if (val !== oldVal) {
        const time = val + this.offset
        const lrc = this.queryLyric(time, this.lyricArr)
        if (lrc.time !== this.curLyric.time) {
          this.scrollLRC(lrc)
          this.$emit('lrc-change', lrc)
        }
        this.curLyric = lrc
      }
    },
    sourceLyric(val, oldVal) {
      if (val !== oldVal) {
        this.lyricArr = this.parseLyric(this.sourceLyric)
        const time = this.curTime + this.offset
        const lrc = this.queryLyric(time, this.lyricArr)
        if (lrc.time !== this.curLyric.time) {
          this.scrollLRC(lrc)
          this.$emit('lrc-change', lrc)
        }
        this.curLyric = lrc
      }
    }
  },
  mounted() {
    this.lyricArr = this.parseLyric(this.sourceLyric)
  },
  methods: {
    parseLyric(sourceLyric) {
      const lrcArr = []
      const arr = sourceLyric.split('\n')
      arr.forEach((item) => {
        const reg = /\[\d{1,2}:\d{1,2}\.\d+\]/g
        const res = item.match(reg)
        if (res) {
          let text = item.replace(reg, '')
          text = text === '' ? '......' : text
          res.forEach((item1) => {
            const tArr = item1.replace('[', '').replace(']', '').split(':')
            const time = parseInt(tArr[0]) * 60 + parseFloat(tArr[1])
            lrcArr.push({ text, time })
          })
        }
      })
      lrcArr.sort((a, b) => {
        return a.time - b.time
      })
      return lrcArr
    },
    queryLyric(time, lyricArr) {
      const len = lyricArr.length
      if (len >= 2) {
        const minTime = lyricArr[0].time
        const maxTime = lyricArr[len - 1].time
        if (time > minTime && time < maxTime) {
          let index = 0
          for (let i = 0; i < lyricArr.length; i++) {
            const lrcItem = lyricArr[i]
            if (lrcItem.time > time) {
              index = i - 1
              break
            }
          }
          return lyricArr[index]
        } else {
          if (time <= minTime) {
            return lyricArr[0]
          } else {
            return lyricArr[len - 1]
          }
        }
      } else {
        return {}
      }
    },
    scrollLRC(lrc) {
      const _this = this
      const $lrcBox = _this.$el.querySelector('.ui-lyric-container')
      const $lrcList = $lrcBox.querySelector('.ui-lyric-list')
      if (!($lrcBox && $lrcList)) {
        return
      }
      if (lrc.text) {
        const $lrc = $lrcList.querySelector("[data-time='" + lrc.time + "']")
        if (!$lrc) {
          return
        }
        const top = $lrc.offsetTop - ($lrcBox.offsetHeight / 2) + ($lrc.offsetHeight / 2)
        if (top > 0) {
          $lrcList.style.top = -top + 'px'
        } else {
          $lrcList.style.top = 0
        }
      }
    }
  }
}
</script>
<style scoped>
  .ui-lyric-warp{
    width: 100%;
    height: 100%;
    position: relative;
    padding: 10px;
    box-sizing: border-box;
  }
  .ui-lyric-container{
    height: 100%;
    width: 100%;
    overflow: hidden;
    position: relative;
  }
  .ui-lyric-list{
    list-style: none;
    padding: 0;
    margin: 0;
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    transition: all 0.2s;
  }
  .ui-lyric-item{
    line-height: 20px;
    font-size: 12px;
    color: #666666;
    text-align: center;
  }
  .ui-lyric-item.active{
    color: #ffa803;
    font-size: 12px;
  }
  .lyric-loading{
    position: absolute;
    width: 30px;
    height: 8px;
    top: 10px;
    left: 50%;
    margin-left: -15px;
  }
</style>
